﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using VietThinks.Security.Web;
using VietThinks.Security;
using VietThinks.Website;
using VietThinks.Contract;

namespace VietThinks
{
    public class AuthenticationService : FormsAuthenticationServiceBase
    {
        public new const string AuthenticationType = "VietThinks Authentication";
        public const string StaffAuthCookieName = "StaffAuthCookie";

        public AuthenticationService()
        {
            // TODO: apply configuration settings
            this.ExpirationTimeWindow = TimeSpan.FromDays(365);
            this.PersistsAuthentication = false;
            this.PersistsGuestSession = true;
        }

        protected bool PersistsGuestSession { get; set; }

        protected override IUserPrincipal GetUserCredential(string userId, string password)
        {
            var securityService = ServiceProvider.GetService<ISecurityService>();

            return securityService.Authenticate(userId, password);
        }

        protected override void OnAuthenticated(IUserPrincipal user)
        {
            //VisitContext.Session.Abandon(); // new life that is legal
            VisitContext.Session.ClearWithConditions<Website.VisitContext.KeepAfterLoginAttribute>();
            //VisitContext.CartManager.MergeCart(true);
            base.OnAuthenticated(user);
        }

        protected override void OnSignedOut(IUserPrincipal user)
        {
            //VisitContext.Cookie.CookieTemp = null;
            //VisitContext.Cookie.IsAuthenticationTemp = false;

            VisitContext.Session.Abandon(); // new life that is wild

            base.OnSignedOut(user);
        }

        public IUserPrincipal IdentifyVisitor()
        {
            var service = ServiceProvider.GetService<ICustomerService>();

            var visitor = HttpContext.Current.User as IUserPrincipal;

            if (visitor == null || visitor == UserPrincipal.Unidentified
                || (!visitor.UserIdentity.IsAuthenticated && service.GetGuest(visitor.UserIdentity.Id) == null))
            {
                visitor = CreateGuestPrincipal();
            }

            // persist authenticatication
            //CreateAuthenticationTicketFromPrincipal(visitor,
            //    this.ExpirationTimeWindow,
            //    visitor.UserIdentity.IsAuthenticated ? this.PersistsAuthentication : this.PersistsGuestSession);

            return visitor;
        }

        public IUserPrincipal IdentifyStaff()
        {
            var service = ServiceProvider.GetService<ISecurityService>();

            var staffAuth = HttpContext.Current.Request.Cookies[StaffAuthCookieName];

            if (staffAuth == null) // incorrect cookied identity
            {
                return UserPrincipal.Unidentified;
            }

            var staff = service.GetStaffPrincipal(staffAuth.Value);

            if (staff == null)
            {
                return UserPrincipal.Unidentified;
            }

            // persist authenticatication
            var cookie = new HttpCookie(StaffAuthCookieName, staffAuth.Value)
            {
                HttpOnly = true
            };
            HttpContext.Current.Response.Cookies.Add(cookie);

            return staff;
        }

        public bool AuthenticateStaff(string id, string password)
        {
            var service = ServiceProvider.GetService<ISecurityService>();

            var staff = service.AuthenticateStaff(id, password);

            this.OnAuthenticating(staff);

            if (staff != null && staff.Identity.IsAuthenticated)
            {
                var cookie = new HttpCookie(StaffAuthCookieName, staff.UserIdentity.Name)
                {
                    HttpOnly = true
                };
                HttpContext.Current.Response.Cookies.Add(cookie);

                this.OnAuthenticated(staff);

                return true;
            }

            this.OnUnauthenticated(staff);

            return false;
        }

        public void SignOutStaff()
        {
            var cookies = HttpContext.Current.Response.Cookies;
            var removalCookie = new HttpCookie(StaffAuthCookieName, String.Empty)
            {
                Expires = DateTime.Now.AddYears(-50)
            };

            VisitContext.Session.Staff = null;

            cookies.Add(removalCookie);
        }

        private static IUserPrincipal CreateGuestPrincipal()
        {
            var service = ServiceProvider.GetService<ISecurityService>();

            IUserPrincipal guest = null;

            // first, try client-side provided guest Id
            if (VisitContext.Cookie.GuestId.HasValue) // guest Id exists and is provided by client-side (browser)?
            {
                int guestId = VisitContext.Cookie.GuestId.Value;


                if (service.ValidateGuest(guestId)) // client-side provided guest Id is valid?
                {
                    guest = CreateGuestPrincipal(guestId);
                }
            }

            // if client does not provide guest Id or the provided guest Id is not valid, create one
            if (guest == null)
            {
                int guestId = service.CreateGuest();

                // create guest
                guest = CreateGuestPrincipal(guestId);
            }

            // persists client-side guest Id. If one has already existed, its timeout is reset
            VisitContext.Cookie.GuestId = guest.UserIdentity.Id;

            return guest;
        }

        private static IUserPrincipal CreateGuestPrincipal(int guestId)
        {
            IUserIdentity guestIdentity = new UserIdentity(guestId, String.Empty, String.Empty, String.Empty, false);

            IUserPrincipal guestPrincipal = new UserPrincipal(guestIdentity, new string[0]);

            return guestPrincipal;
        }

    }
}
